package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO;
import com.ctshk.rpc.finance.entity.FinanceOnAccount;
import com.ctshk.rpc.finance.entity.FinanceOnAccountCurrencyQuota;
import com.ctshk.rpc.finance.entity.FinanceOnAccountUsageRecord;
import com.ctshk.rpc.finance.mapper.*;
import com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq;
import com.ctshk.rpc.finance.req.onaccount.RollBackQuotaReq;
import com.ctshk.rpc.finance.req.onaccount.UseQuotaReq;
import com.ctshk.rpc.finance.service.IFinanceOnAccountCurrencyQuotaService;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 财务挂账币种额度 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-30
 */
@DubboService
public class FinanceOnAccountCurrencyQuotaServiceImpl extends ServiceImpl<FinanceOnAccountCurrencyQuotaMapper, FinanceOnAccountCurrencyQuota> implements IFinanceOnAccountCurrencyQuotaService {

    @Autowired
    private FinanceOnAccountCurrencyQuotaMapper onAccountCurrencyQuotaMapper;
    @Autowired
    private FinanceOnAccountUsageRecordMapper onAccountUsageRecordMapper;
    @Autowired
    private FinanceBillMapper billMapper;
    @Autowired
    private FinanceOnAccountMapper onAccountMapper;
    @Autowired
    private FinanceOnAccountApplyMapper onAccountApplyMapper;

    @DubboReference
    private ISysDepartmentService departmentService;



    /**
     * 查询额度
     *
     * @param req
     * @return
     */
    @Override
    public Result<QueryQuotaDTO> queryQuota(QueryQuotaReq req) {
        if (Objects.equals(req.getAccountType(),1)){
            //大客户挂账
            QueryWrapper<FinanceOnAccount> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("account_id",req.getAccountId());
            queryWrapper.eq("is_deleted",0);
            FinanceOnAccount onAccount = onAccountMapper.selectOne(queryWrapper);
            if (onAccount == null){
                throw new BusinessException(SystemError.FINANCE_ERROR_17032);
            }
            //是否过期
            LocalDateTime now = LocalDateTime.now();
            if (onAccount.getEffectiveTime().isBefore(now)){
                throw new BusinessException(SystemError.FINANCE_ERROR_17032);
            }
        }
        //查询额度
        QueryQuotaDTO dto = onAccountCurrencyQuotaMapper.queryQuota(req.getAccountType(),req.getDeptId(),req.getAccountId(),req.getCurrencyId(),req.getBusinessType());
        boolean tag = false;
        if (dto != null && StringUtils.isNotBlank(dto.getBusinessTypeList())){
            List<Integer> businessTypeList = JSON.parseArray(dto.getBusinessTypeList(), Integer.class);
            for (Integer businessType : businessTypeList) {
                if (Objects.equals(req.getBusinessType(),businessType)){
                    tag = true;
                    break;
                }
            }
        }
        if (tag){
            return Result.success(dto);
        }
        return Result.success(null);
    }

    /**
     * 使用额度
     *
     * @param reqList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result useQuota(List<UseQuotaReq> reqList) {
        List<FinanceOnAccountUsageRecord> list = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for (UseQuotaReq req : reqList){
            //查询财务挂账信息
            QueryWrapper<FinanceOnAccount> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("account_type",req.getAccountType());
            queryWrapper.eq(Objects.equals(req.getAccountType(),1),"account_id",req.getAccountId());
            queryWrapper.eq(Objects.equals(req.getAccountType(),2),"dept_id",req.getDeptId());
            queryWrapper.eq("is_deleted",0);
            FinanceOnAccount onAccount = onAccountMapper.selectOne(queryWrapper);
            if (onAccount == null){
                if (Objects.equals(req.getAccountType(),1)){
                    return Result.failed( new BusinessException(SystemError.FINANCE_BILL_17013));
                }else{
                    //内部挂账 -> 创建账号
                    onAccount = new FinanceOnAccount();
                    onAccount.setId(SnowflakeIdWorker.nextId());
                    onAccount.setAccountType(req.getAccountType());
                    onAccount.setDeptId(req.getDeptId());
                    SysDepartmentDTO departmentDTO = departmentService.queryOne(req.getDeptId());
                    if (departmentDTO != null){
                        onAccount.setDeptCode(departmentDTO.getDeptCode());
                        onAccount.setDeptName(departmentDTO.getTitle());
                    }
                    onAccount.setGmtCreate(now);
                    onAccount.setCreateId(req.getUserId());
                    onAccount.setIsDeleted(0);
                    int insert = onAccountMapper.insert(onAccount);
                    if (insert <= 0){
                        return Result.failed(new BusinessException(SystemError.SYS_408));
                    }
                }
            }
            if (Objects.equals(req.getAccountType(),1)){
                //查询额度
                QueryQuotaDTO dto = onAccountCurrencyQuotaMapper.queryQuota(req.getAccountType(),req.getDeptId(),req.getAccountId(), req.getCurrencyId(), req.getBusinessType());
                if (dto == null){
                    return Result.failed( new BusinessException(SystemError.FINANCE_BILL_17016));
                }
                //是否过期
                if (onAccount.getEffectiveTime().isBefore(now)){
                    throw new BusinessException(SystemError.FINANCE_ERROR_17032);
                }
                //可用余额
                BigDecimal availableAmount = dto.getAvailableAmount();
                //查询审批中的金额
                BigDecimal lockedAmount = onAccountUsageRecordMapper.sumApprovalingAmount(onAccount.getAccountId(), req.getCurrencyId());
                if (lockedAmount != null){
                    availableAmount = availableAmount.subtract(lockedAmount);
                }
                if (availableAmount.compareTo(req.getAmount()) < 0){
                    throw new BusinessException(SystemError.FINANCE_BILL_17017,lockedAmount);
                }
            }
            //新增挂账使用记录
            FinanceOnAccountUsageRecord usageRecord = EntityUtil.copy(req,FinanceOnAccountUsageRecord.class);
            usageRecord.setId(SnowflakeIdWorker.nextId());
            usageRecord.setOnAccountId(onAccount.getId());
            usageRecord.setSaleOrderId(req.getSaleOrderId());
            usageRecord.setBillType(1);
            usageRecord.setTotalAmount(req.getAmount());
            if (CollectionUtils.isNotEmpty(req.getResourceInfo())){
                usageRecord.setResourceInfo(JSON.toJSONString(req.getResourceInfo()));
            }
            usageRecord.setBillNumber(req.getBillNumber());
            usageRecord.setGmtCreate(now);
            usageRecord.setCreateId(req.getUserId());
            usageRecord.setIsDeleted(0);
            list.add(usageRecord);
            //扣掉额度
            QueryWrapper<FinanceOnAccountCurrencyQuota> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("on_account_id",onAccount.getId());
            queryWrapper1.eq("currency_id",req.getCurrencyId());
            queryWrapper1.eq("is_deleted",0);
            FinanceOnAccountCurrencyQuota currencyQuota = onAccountCurrencyQuotaMapper.selectOne(queryWrapper1);
            if (currencyQuota == null){
                if (Objects.equals(req.getAccountType(),1)){
                    return Result.failed( new BusinessException(SystemError.FINANCE_BILL_17013));
                }else{
                    //内部挂账 -> 新增额度记录
                    currencyQuota = new FinanceOnAccountCurrencyQuota();
                    currencyQuota.setId(SnowflakeIdWorker.nextId());
                    currencyQuota.setOnAccountId(onAccount.getId());
                    currencyQuota.setCurrencyId(req.getCurrencyId());
                    currencyQuota.setCurrency(req.getCurrencyName());
                    currencyQuota.setTotalAmount(BigDecimal.ZERO);
                    currencyQuota.setUsedAmount(req.getAmount());
                    currencyQuota.setWriteOffAmount(BigDecimal.ZERO);
                    currencyQuota.setGmtCreate(now);
                    currencyQuota.setCreateId(req.getUserId());
                    currencyQuota.setIsDeleted(0);
                    int insert = onAccountCurrencyQuotaMapper.insert(currencyQuota);
                    if (insert <= 0){
                        return Result.failed(new BusinessException(SystemError.SYS_408));
                    }
                }
            }else{
                //更新额度
                currencyQuota.setUsedAmount(currencyQuota.getUsedAmount().add(req.getAmount()));
                currencyQuota.setModifiedId(req.getUserId());
                int update = onAccountCurrencyQuotaMapper.updateById(currencyQuota);
                if (update <= 0){
                    return Result.failed(new BusinessException(SystemError.SYS_408));
                }
            }
        }
        if (list.size() == 0){
            return Result.failed( new BusinessException(SystemError.FINANCE_ERROR_17036));
        }
        Integer batch = onAccountUsageRecordMapper.insertBatchSomeColumn(list);
        if (batch < list.size()){
            return Result.failed(new BusinessException(SystemError.SYS_408));
        }
        return Result.success();
    }

    /**
     * 回滚挂账额度（内部接口）
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result rollBackQuota(RollBackQuotaReq req) {
        if (req.getOrderId() == null && StringUtils.isBlank(req.getCollectionNumber())){
            return Result.failed(new BusinessException(SystemError.SYS_402));
        }
        QueryWrapper<FinanceOnAccountUsageRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(req.getOrderId() != null,"sale_order_id",req.getOrderId());
        queryWrapper.eq(StringUtils.isNotBlank(req.getCollectionNumber()),"bill_number",req.getCollectionNumber());
        queryWrapper.eq("is_deleted",0);
        FinanceOnAccountUsageRecord usageRecord = onAccountUsageRecordMapper.selectOne(queryWrapper);
        if (usageRecord == null){
            return Result.failed(new BusinessException(SystemError.FINANCE_ERROR_17040));
        }
        //新增退额度记录
        FinanceOnAccountUsageRecord newRecord = EntityUtil.copy(usageRecord,FinanceOnAccountUsageRecord.class);
        newRecord.setId(SnowflakeIdWorker.nextId());
        newRecord.setCreateId(req.getUserId());
        newRecord.setModifiedId(null);
        newRecord.setGmtCreate(LocalDateTime.now());
        newRecord.setGmtModified(null);
        newRecord.setIsDeleted(0);
        newRecord.setTotalAmount(req.getAmount());
        newRecord.setBillType(2);
        newRecord.setBillNumber(req.getRefundNumber());
        int insert = onAccountUsageRecordMapper.insert(newRecord);
        //回滚额度
        QueryWrapper<FinanceOnAccountCurrencyQuota> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("on_account_id",usageRecord.getOnAccountId());
        queryWrapper1.eq("currency_id",usageRecord.getCurrencyId());
        queryWrapper1.eq("is_deleted",0);
        FinanceOnAccountCurrencyQuota currencyQuota = onAccountCurrencyQuotaMapper.selectOne(queryWrapper1);
        if (currencyQuota == null){
            return Result.failed(new BusinessException(SystemError.SYS_411));
        }
        currencyQuota.setUsedAmount(currencyQuota.getUsedAmount().subtract(newRecord.getTotalAmount()));
        currencyQuota.setModifiedId(req.getUserId());
        int update = onAccountCurrencyQuotaMapper.updateById(currencyQuota);

        if (insert <= 0 || update <= 0){
            throw new BusinessException(SystemError.SYS_408);
        }
        return Result.success(newRecord.getId());
    }
}
